<template>
  <div style="display: flex;justify-content: space-around;">
    <div style="height: 900px;">
      <div class="sticky">
        <DataTree :data-tree="dataTree" :screen-height="screenHeight" :first-node="treeFirstNode" :default-props="treeDefaultProps" :default-label="true">
          <!-- 一级菜单 -->
          <template slot="parent-icon" slot-scope="{ parentData }">
            <slot name="tableFirst" :parentData="{belong:parentData.belong}" />
          </template>
          <!-- 二级菜单 -->
          <template slot="children-icon" slot-scope="{ childrenData }">
            <slot name="tableSecond" :childrenData="{data:childrenData.data,belong:childrenData.belong}" />
          </template>
        </DataTree>
      </div>
    </div>
    <!-- <div class="tableDesign d-flex"> -->
    <!-- 中间区域 -->
    <div class="content flex-1 p" :style="{'background':tableContentBackground}" @mousedown.stop="changeTableSeting({ type: 'table' })">
      <!-- 简易模式 -->
      <easyModeTable
        v-show="tableMode === 'easy'"
        ref="easyTable"
        :options.sync="tableOptions"
        :cell-options.sync="cellOptions"
        :data-transfer-data="dataTransferData"
        @changeTableSeting="changeTableSeting"
      />
      <!-- 混合模式 -->
      <blendModeTable
        v-show="tableMode === 'blend'"
        ref="blendTable"
        :options.sync="tableOptions"
        :cell-options.sync="cellOptions"
        :data-transfer-data="dataTransferData"
        :save-mapping-function="saveMappingFunction"
        @changeTableSeting="changeTableSeting"
        @tableJsonChange="tableJsonChange"
        v-on="$listeners"
      />
    </div>
    <!-- </div> -->
    <!-- 右侧操作 -->
    <div style="height: 900px;">
      <div class="sticky" style="padding-bottom: 5px;">
        <table-properties
          ref="tableProperties"
          :screen-height="screenHeight"
          :tree-data="dataTree"
          :mode="tableMode"
          :state="state"
          :repeal-disabled="operateIndex === 0"
          :restore-disabled="operateIndex === tableJsonOperateArray.length - 1"
          :table-property-hidden="tablePropertyHidden"
          :cell-property-hidden="cellPropertyHidden"
          @mousedown.native.stop
          @createTable="setTable"
          @changeTableOptions="changeTableOptions"
          @changeCellOptions="changeCellOptions"
          @operateHistory="operateHistory"
        >
          <template slot="tableExtendedPropertyTop" slot-scope="{ data }">
            <slot name="tableExtendedPropertyTop" :data="data" />
          </template>
          <template slot="tableExtendedProperty" slot-scope="{ data }">
            <slot name="tableExtendedProperty" :data="data" />
          </template>
          <template slot="cellTableExtendedProperty" slot-scope="{ data }">
            <slot name="cellTableExtendedProperty" :data="data" />
          </template>
        </table-properties>
      </div>
    </div>
  </div>
</template>
<script>
import DataTree from './components/DataTree.vue'
import TableProperties from './components/TableProperties.vue'
import easyModeTable from './components/easyModeTable/easyTable.vue'
import blendModeTable from './components/blendModeTable/blendTable.vue'
import * as generalTableConstant from '@/components/GeneralTable/generalTableConstant'
import { formatDate } from '@/utils/date-utils.js'
export default {
  name: 'GeneralTableDesign',
  components: { DataTree, TableProperties, easyModeTable, blendModeTable },
  props: {
    // 数据树
    dataTree: {
      type: Array,
      default() {
        return []
      }
    },
    // 以什么字段区分是否为一级
    treeFirstNode: {
      type: String,
      default() {
        return 'firstNode'
      }
    },
    // 数据树默认配置
    treeDefaultProps: {
      type: Object,
      default() {
        return {
          children: 'children',
          label: 'label'
        }
      }
    },
    // 除去标题的高度
    screenHeight: {
      type: Number,
      default: 700
    },
    // 需要隐藏的表格属性
    tablePropertyHidden: {
      type: Array,
      default: () => []
    },
    // 需要隐藏的单元格属性
    cellPropertyHidden: {
      type: Array,
      default: () => []
    },
    // 表格模式  easy->简易  blend->混合
    tableMode: {
      type: String,
      default: 'easy'
    },
    // 表格内容背景色
    tableContentBackground: {
      type: String,
      default() {
        // 默认透明色
        return '#00000000'
      }
    },
    saveMappingFunction: {
      type: Function,
      default(selectCells, renderTBodyData) {
        return ''
      }
    }
  },
  data() {
    return {
      // defaultProps: {
      //   children: 'children',
      //   label: 'label'
      // },
      tableJsonOperateArray: [], // 表格json操作数组 用作表格操作历史记录
      operateIndex: -1, // 操作记录索引 用于标识在历史记录中的索引
      operateHistoryDataFlag: false, // 操作历史记录数据标志
      emptyText: '暂无数据',
      treeKey: '',
      isActive: true,
      state: 'table',
      tableVal: {},
      tableOptions: JSON.parse(JSON.stringify(generalTableConstant.TABLE_OPTIONS)),
      cellOptions: JSON.parse(JSON.stringify(generalTableConstant.CELL_OPTIONS)),
      tableSetDataCache: { // 缓存简易混合的数据(左侧数据集映射关系+表格属性+单元格属性)
        easy: {
          tableOptions: {},
          cellOptions: {},
          isCache: false
        },
        blend: {
          tableOptions: {},
          cellOptions: {},
          isCache: false
        }
      },
      constCache: {},			 // 切换模式并且第一次缓存的时候需要用到
      dataTransferData: {} // 当前拖拽的数据
    }
  },
  watch: {
    tableMode() {
      const defaultTableOptions = JSON.parse(JSON.stringify(generalTableConstant.TABLE_OPTIONS))
      // 首次进来不执行
      if (!this.tableSetDataCache.easy.isCache && !this.tableSetDataCache.blend.isCache) return
      // 没缓存过则取constCache的值
      if (!this.tableSetDataCache[this.tableMode].isCache) {
        this.tableSetDataCache[this.tableMode] = JSON.parse(JSON.stringify(this.constCache))
        this.tableSetDataCache[this.tableMode]['tableOptions'].bodyRowNum = defaultTableOptions.bodyRowNum
        this.tableSetDataCache[this.tableMode]['tableOptions'].colNum = defaultTableOptions.colNum
        // 简易模式 1 混合模式 0
        this.tableSetDataCache[this.tableMode]['tableOptions'].headRowNum = (this.tableMode === 'easy' ? 1 : 0)
      }
      this.tableOptions = JSON.parse(JSON.stringify(this.tableSetDataCache[this.tableMode].tableOptions))
      this.cellOptions = JSON.parse(JSON.stringify(this.tableSetDataCache[this.tableMode].cellOptions))
      this.$forceUpdate()
      // 创建另一个表格
      if (!this.tableSetDataCache[this.tableMode].isCache) {
        this.setTable(this.tableOptions)
        // this.$refs[this.tableMode === 1 ? 'blendTable' : 'easyTable'].setTable(this.tableSetDataCache[mode]['tableOptions'].headRowNum, this.tableSetDataCache[mode]['tableOptions'].bodyRowNum, this.tableSetDataCache[mode]['tableOptions'].colNum)
        this.tableSetDataCache[this.tableMode].isCache = true
      }

      // 初始化配置项
      this.$refs.tableProperties.tableProperty = JSON.parse(JSON.stringify(this.tableOptions))
      this.$refs.tableProperties.tablePropertyCopy = JSON.parse(JSON.stringify(this.tableOptions))
      this.$refs.tableProperties.cellProperty = this.cellOptions
    }
  },
  created() {
    this.constCache = {
      tableOptions: JSON.parse(JSON.stringify(this.tableOptions)),
      cellOptions: JSON.parse(JSON.stringify(this.cellOptions))
    }
  },
  mounted() {
    this.$EventBus.$on('dataTransferData', data => {
      this.dataTransferData = data
    })
    // 简易模式下设置表头
    if (this.tableMode === 'easy') {
      this.tableOptions.headRowNum = 1
    }
  },
  methods: {
    sendEasyTable(val) {
      this.$refs.tableProperties.receiveInputValue(val)
    },
    /**
     * 组件初始化
     * @param {Object} tableJson
     */
    componentInit(tableJson) {
      this.$nextTick(() => {
        if (tableJson) {
          // 回显表格
          this.getTableRef().echoTable(tableJson)
          // 获取表格配置信息
          this.tableOptions = JSON.parse(tableJson).options
          this.$refs.tableProperties.tableProperty = JSON.parse(JSON.stringify(this.tableOptions))
          this.$refs.tableProperties.tablePropertyCopy = JSON.parse(JSON.stringify(this.tableOptions))
        }
        else {
          // 创建表格
          this.setTable(this.tableOptions)
          // 初始化配置项
          this.$refs.tableProperties.tableProperty = JSON.parse(JSON.stringify(this.tableOptions))
          this.$refs.tableProperties.tablePropertyCopy = JSON.parse(JSON.stringify(this.tableOptions))
          this.$refs.tableProperties.cellProperty = this.cellOptions
        }
        this.cacheInit()
      })
    },
    /**
     * 向外提供获取表格json的方法
     */
    getTableJSON() {
      return this.getTableRef().getTableJSON()
    },
    /**
     * 缓存当前模式的数据
     */
    cacheInit() {
      const obj = {
        tableOptions: JSON.parse(JSON.stringify(this.tableOptions)),
        cellOptions: JSON.parse(JSON.stringify(this.cellOptions)),
        isCache: true
      }

      this.tableSetDataCache[this.tableMode] = JSON.parse(JSON.stringify(obj))
    },
    /**
     * 根据当前模式获取表格组件的ref
     */
    getTableRef() {
      return this.$refs[this.tableMode + 'Table']
    },
    /**
     * 获取表格属性组件的ref
     */
    getTablePropertiesRef() {
      return this.$refs.tableProperties
    },
    /**
     * 创建表格
     * @param {Object} options
     */
    setTable(options) {
      this.getTableRef().setTable(options.headRowNum, options.bodyRowNum, options.colNum)
    },
    /**
     * 表格和单元格的状态切换
     * @param {Object} e
     */
    changeTableSeting(e) {
      this.state = e.type
      if (e.type === 'cell') {
        if (e.data) {
          this.cellOptions = e.data
          this.$refs.tableProperties['cellProperty'] = e.data
        }
      }
      else {
        this.getTableRef().clearSelect()
        if (e.data) {
          this.tableOptions = e.data
          this.$refs.tableProperties['tableProperty'] = e.data
        }
      }

      this.$forceUpdate()
    },
    /**
     * 单个表格属性重新赋值
     * @param {Object} e
     */
    changeTableOptions(e) {
      this.tableOptions[e.key] = e.value
      this.tableOptions.changeKey = [e.key]
      // 刷新表格样式
      this.getTableRef().setTableStyle()
      this.cacheInit()
    },
    /**
     * 单个表格扩展属性重新赋值
     *  @param {Object} e
     */
    changeTableExtendOptions(e) {
      // 刷新表格样式
      this.getTableRef().changeTableExtendOptions(e)
    },
    /**
     * 单个单元格属性重新赋值
     * @param {Object} e
     */
    changeCellOptions(e) {
      // 单个属性的进行赋值更改
      if (e.key === 'tableCellHeight') this.cellOptions.tableCellHeight = e.value
      if (e.key === 'tableCellWidth') this.cellOptions.tableCellWidth = e.value
      if (e.key === 'size') this.cellOptions.size = e.value
      if (e.key === 'color' || e.key === 'isColorChange') {
        this.cellOptions.isColorChange = e.key === 'color'
        this.cellOptions.color = e.value
        this.cellOptions.changeKey = ['isColorChange', 'color']
        return
      }
      if (e.key === 'align') this.cellOptions.align = e.value
      if (e.key === 'valign') this.cellOptions.valign = e.value
      if (e.key === 'isWeight') this.cellOptions.isWeight = e.value
      if (e.key === 'isItalic') this.cellOptions.isItalic = e.value
      if (e.key === 'underline') this.cellOptions.underline = e.value
      if (e.key === 'isShow') this.cellOptions.isShow = e.value
      if (e.key === 'cellFill') this.cellOptions.cellFill = e.value
      if (e.key === 'topBorderColor') this.cellOptions.topBorderColor = e.value
      if (e.key === 'bottomBorderColor') this.cellOptions.bottomBorderColor = e.value
      if (e.key === 'leftBorderColor') this.cellOptions.leftBorderColor = e.value
      if (e.key === 'rightBorderColor') this.cellOptions.rightBorderColor = e.value
      this.cellOptions.changeKey = [e.key]
      this.cacheInit()
    },
    /**
     * 屏蔽树自身的drop行为
     * @param {Object} draggingNode
     * @param {Object} dropNode
     * @param {Object} type
     */
    allowDrop(draggingNode, dropNode, type) {
      return false
    },
    /**
     * 使节点可拖拽
     * @param {Object} draggingNode
     */
    allowDrag(draggingNode) {
      return !draggingNode.childNodes.length
    },
    /**
     * 左侧数据拖拽完成方法
     * @param params
     */
    targetDropEnd({ renderTBodyData, content, selectFlag }) {
      // 向外抛出
      this.$emit('targetDropEnd', { renderTBodyData, content, selectFlag })
    },
    // 表格内部清空内容方法
    clearContent({ renderTBodyData, selectCellsData }) {
      // 向外抛出
      this.$emit('clearContent', { renderTBodyData, selectCellsData })
    },
    /**
     * 表格json对象变化 触发
     * @param oldTableJsonObj 修改前表格json配置
     * @param newTableJsonObj 修改后表格json配置
     */
    tableJsonChange({ oldTableJsonObj, newTableJsonObj }) {
      // 如果操作历史记录标志为true则不进行后续操作
      if (this.operateHistoryDataFlag) {
        return
      }
      // 操作记录索引不等于数组的最后一个下标  需要销毁该索引之后的记录
      if (this.operateIndex !== this.tableJsonOperateArray.length - 1) {
        // 删除的索引   操作记录索引+1
        const deleteIndex = this.operateIndex + 1
        // 删除的长度   总长度 - (索引下标+1)
        const deleteLen = this.tableJsonOperateArray.length - (this.operateIndex + 1)
        // 销毁当前索引之后的历史记录
        this.tableJsonOperateArray.splice(deleteIndex, deleteLen)
      }
      const curDate = new Date()
      // 操作记录数据
      const operateData = {
        historyTime: curDate.getTime(), // 历史记录时间毫秒数
        historyTimeFormat: formatDate(curDate, 'yyyy-MM-dd hh:mm:ss'), // 历史记录时间格式化
        preSecond: 0, // 距离上一次历史记录间隔秒数
        tableJson: JSON.stringify(newTableJsonObj) // 表格json字符串
      }
      // 取数组最后一条数据
      const lastData = this.tableJsonOperateArray.length > 0 ? this.tableJsonOperateArray[this.tableJsonOperateArray.length - 1] : null
      // 获取历史记录时间毫秒数
      const historyTime = lastData ? lastData.historyTime : 0
      // 获取当前时间毫秒数
      const curDateTime = new Date().getTime()
      // 相差秒数
      const subSecond = (curDateTime - historyTime) / 1000
      // 设置间隔秒数
      operateData.preSecond = subSecond
      // 超过1秒
      if (subSecond > 1) {
        // 向后插入数据
        this.tableJsonOperateArray.push(operateData)
      // 不足1秒
      } else {
        // 更新最后一条数据
        this.$set(this.tableJsonOperateArray, this.tableJsonOperateArray.length - 1, operateData)
      }
      // 如果长度 大于50
      if (this.tableJsonOperateArray.length > 50) {
        // 删除第一个元素
        this.tableJsonOperateArray.shift()
      }
      // 设置操作记录索引为数组最后一个下标
      this.operateIndex = this.tableJsonOperateArray.length - 1
    },
    /**
     * 操作历史记录
     * @param operateType 操作类型  撤销(repeal) 或者 还原(restore)
     */
    operateHistory(operateType) {
      // 操作历史记录必须保证 历史记录数组有数据
      if (!this.tableJsonOperateArray.length) {
        // 无数据直接返回
        return
      }
      // 撤销操作且当前历史记录索引等于0
      // 或者 还原操作且当前列数记录索引等于最后一位
      if ((operateType === 'repeal' && this.operateIndex === 0) ||
          (operateType === 'restore' && this.operateIndex === this.tableJsonOperateArray.length - 1)) {
        // 返回
        return
      }
      // 开启操作历史记录标志
      this.operateHistoryDataFlag = true
      // 撤销
      if (operateType === 'repeal') {
        // 操作索引前移
        this.operateIndex--
      // 还原
      } else if (operateType === 'restore') {
        // 操作索引后移
        this.operateIndex++
      }
      // 取出历史记录数据
      const historyData = this.tableJsonOperateArray[this.operateIndex]
      // 获取表格json数据
      const tableJson = historyData.tableJson
      // 转换tableJson对象
      const tableJsonObj = JSON.parse(tableJson)
      this.$refs.tableProperties.tableProperty = JSON.parse(JSON.stringify(this.tableOptions))
      this.$refs.tableProperties.tablePropertyCopy = JSON.parse(JSON.stringify(this.tableOptions))
      // 刷新表格
      this.getTableRef().refreshTable(tableJson)
      // 获取表格配置信息
      this.tableOptions = tableJsonObj.options
      // 获取表格扩展属性值
      const extendOptions = tableJsonObj.extendOptions
      // 获取预览主题色编码
      const previewThemeColorCode = extendOptions ? extendOptions.previewThemeColorCode : ''
      // 预览主题色不为空
      if (previewThemeColorCode) {
        // 触发修改主题色方法
        this.$EventBus.$emit('updatePreviewThemeColorCode', previewThemeColorCode)
      }
      // 触发修改配置模式方法
      this.$EventBus.$emit('configModeChange', this.tableOptions.configMode)
      // 刷新业务数据
      this.$EventBus.$emit('refreshServiceData', {
        data: tableJsonObj.data
      })
      this.$forceUpdate()
      setTimeout(() => {
        this.operateHistoryDataFlag = false
      }, 0)
    }
  }
}
</script>

<style lang="scss" scoped>
  .sticky{
    position: sticky;
    top: 10px;
  }
</style>
